#include<iostream>
#include<fstream>
#include<cmath>
#include<vector>
#include "../programming1/EquationSolver.h"
#include "ppForm_LinearSpline.h"
#include "ppForm_CubicSpline.h"
using namespace std;

class Func : public Function {
    public:
        virtual double operator () (const double& x)  {
            return 1 / (1 + 25*x*x);
        }
        virtual double diff (const double& x)  {
            return -50 * x / (1 + 25*x*x) / (1 + 25*x*x);
        }
        virtual double diff2 (const double& x) {
            return (-50 + 3750*x*x) / (1 + 25*x*x) / (1 + 25*x*x) / (1 + 25*x*x);
        }
} func;

int main() {
	LinearSpline L5 = LinearSplineInterpolation(func, -1.0, 1.0, 5);
	LinearSpline L10 = LinearSplineInterpolation(func, -1.0, 1.0, 10);
	LinearSpline L20 = LinearSplineInterpolation(func, -1.0, 1.0, 20);
	LinearSpline L40= LinearSplineInterpolation(func, -1.0, 1.0, 40);
	LinearSpline L80 = LinearSplineInterpolation(func, -1.0, 1.0, 80);

    ofstream out1("ppForm_linear5.csv");
	out1 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out1 << i * 0.001 << ',' << L5.getValue(i * 0.001) << endl;
	ofstream out2("ppForm_linear10.csv");
	out2 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out2 << i * 0.001 << ',' << L10.getValue(i * 0.001) << endl;
	ofstream out3("ppForm_linear20.csv");
	out3 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out3 << i * 0.001 << ',' << L20.getValue(i * 0.001) << endl;
	ofstream out4("ppForm_linear40.csv");
	out4 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out4 << i * 0.001 << ',' << L40.getValue(i * 0.001) << endl;
	ofstream out5("ppForm_linear80.csv");
	out5 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out5 << i * 0.001 << ',' << L80.getValue(i * 0.001) << endl;

	CubicSpline C5 = CubicSplineInterpolation(func, -1.0, 1.0, 5, "complete");
	CubicSpline C10 = CubicSplineInterpolation(func, -1.0, 1.0, 10, "complete");
	CubicSpline C20 = CubicSplineInterpolation(func, -1.0, 1.0, 20, "complete");
	CubicSpline C40 = CubicSplineInterpolation(func, -1.0, 1.0, 40, "complete");
	CubicSpline C80 = CubicSplineInterpolation(func, -1.0, 1.0, 80, "complete");
    
    ofstream out6("ppForm_cubic_complete5.csv");
	out6 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out6 << i * 0.001 << ',' << C5.getValue(i * 0.001) << endl;
	ofstream out7("ppForm_cubic_complete10.csv");
	out7 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out7 << i * 0.001 << ',' << C10.getValue(i * 0.001) << endl;
	ofstream out8("ppForm_cubic_complete20.csv");
	out8 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out8 << i * 0.001 << ',' << C20.getValue(i * 0.001) << endl;
	ofstream out9("ppForm_cubic_complete40.csv");
	out9 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out9 << i * 0.001 << ',' << C40.getValue(i * 0.001) << endl;
	ofstream out10("ppForm_cubic_complete80.csv");
	out10 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out10 << i * 0.001 << ',' << C80.getValue(i * 0.001) << endl;
    
    CubicSpline N5 = CubicSplineInterpolation(func, -1.0, 1.0, 5, "natural");
	CubicSpline N10 = CubicSplineInterpolation(func, -1.0, 1.0, 10, "natural");
	CubicSpline N20 = CubicSplineInterpolation(func, -1.0, 1.0, 20, "natural");
	CubicSpline N40 = CubicSplineInterpolation(func, -1.0, 1.0, 40, "natural");
	CubicSpline N80 = CubicSplineInterpolation(func, -1.0, 1.0, 80, "natural");

    ofstream out11("ppForm_cubic_natural5.csv");
	out11 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out11 << i * 0.001 << ',' << N5.getValue(i * 0.001) << endl;
	ofstream out12("ppForm_cubic_natural10.csv");
	out12 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out12 << i * 0.001 << ',' << N10.getValue(i * 0.001) << endl;
	ofstream out13("ppForm_cubic_natural20.csv");
	out13 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out13 << i * 0.001 << ',' << N20.getValue(i * 0.001) << endl;
	ofstream out14("ppForm_cubic_natural40.csv");
	out14 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out14 << i * 0.001 << ',' << N40.getValue(i * 0.001) << endl;
	ofstream out15("ppForm_cubic_natural80.csv");
	out15 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out15 << i * 0.001 << ',' << N80.getValue(i * 0.001) << endl;

    
    CubicSpline ssd5 = CubicSplineInterpolation(func, -1.0, 1.0, 5, "ssd");
	CubicSpline ssd10 = CubicSplineInterpolation(func, -1.0, 1.0, 10, "ssd");
	CubicSpline ssd20 = CubicSplineInterpolation(func, -1.0, 1.0, 20, "ssd");
	CubicSpline ssd40 = CubicSplineInterpolation(func, -1.0, 1.0, 40, "ssd");
	CubicSpline ssd80 = CubicSplineInterpolation(func, -1.0, 1.0, 80, "ssd");

    ofstream out16("ppForm_cubic_ssd5.csv");
	out16 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out16 << i * 0.001 << ',' << ssd5.getValue(i * 0.001) << endl;
	ofstream out17("ppForm_cubic_ssd10.csv");
	out17 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out17 << i * 0.001 << ',' << ssd10.getValue(i * 0.001) << endl;
	ofstream out18("ppForm_cubic_ssd20.csv");
	out18 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out18 << i * 0.001 << ',' << ssd20.getValue(i * 0.001) << endl;
	ofstream out19("ppForm_cubic_ssd40.csv");
	out19 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out19 << i * 0.001 << ',' << ssd40.getValue(i * 0.001) << endl;
	ofstream out20("ppForm_cubic_ssd80.csv");
	out20 << "x,y" << '\n';
	for(int i = -999; i <= 999; ++ i) out20 << i * 0.001 << ',' << ssd80.getValue(i * 0.001) << endl;
}

